home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
TeX 1995 July
/
TeX CD-ROM July 1995 (Disc 1)(Walnut Creek)(1995).ISO
/
dviware
/
dvitops
/
tpic.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-01-25
|
13KB
|
550 lines
static char rcsid[] = "$Header: /usr/jjc/dvitops/RCS/tpic.c,v 1.4 90/08/14 13:03:50 jjc Rel $";
#include "dvitops.h"
#ifdef TPIC_SUPPORT
/* Dotted lines look a bit anaemic; so we add this many milli-inches to
the pen size of a dotted line. */
#define DOTTED_LINE_WIDTH_ADDITION 3
/* flags in tpic_object is or'ed from these */
#define ARC 1
#define SPLINE 2
#define SHADED 4
#define INVISIBLE 8
#define DOTTED 16
#define DASHED 32
struct point {
integer x;
integer y;
};
struct tpic_object {
struct tpic_object *next;
integer h, v;
int region;
unsigned flags;
integer pen_size;
float shade;
union {
struct {
float dash_width;
int npoints;
struct point point_vector[2]; /* may be bigger than this */
} p;
struct {
integer cx;
integer cy;
integer rx;
integer ry;
float s;
float e;
} a;
} u;
};
#ifdef PROTO
static void draw_path(FILE *psfp, double sc, integer h, integer v,
struct point *pv, int np, int closed);
static void draw_spline(FILE *psfp, double sc, integer h, integer v,
struct point *pv, int np);
static void draw_ellipse(FILE *psfp, double sc, integer h, integer v,
integer cx, integer cy, integer rx, integer ry);
static void draw_arc(FILE *psfp, double sc, integer h, integer v,
integer cx, integer cy, integer r, double s, double e);
#else
static void draw_path();
static void draw_spline();
static void draw_ellipse();
static void draw_arc();
#endif
struct tpic_object *tpic_object_list = NULL;
#define TPIC_CODE(c1, c2) (((unsigned char)(c1) << 8) + (unsigned char)(c2))
/* return 1 if it was a tpic_special, 0 otherwise */
int tpic_special(pass, arg, x, y)
int pass;
char *arg;
integer x, y;
{
static integer current_pen_size = 8;
static unsigned tpic_flags = 0;
static float shade = 0.0;
static int npoints = 0;
static int maxpoints = 0;
static struct point *point_vector = 0;
double dash_width;
int complete = 0;
while (*arg == ' ')
arg++;
if (arg[0] == '\0' || arg[1] == '\0'
|| (arg[2] != ' ' && arg[2] != '\0'))
return 0;
if (pass != PASS2) {
switch (TPIC_CODE(arg[0], arg[1])) {
case TPIC_CODE('p', 'n'):
case TPIC_CODE('p', 'a'):
case TPIC_CODE('s', 'p'):
case TPIC_CODE('d', 'a'):
case TPIC_CODE('d', 't'):
case TPIC_CODE('i', 'p'):
case TPIC_CODE('f', 'p'):
case TPIC_CODE('i', 'a'):
case TPIC_CODE('a', 'r'):
case TPIC_CODE('s', 'h'):
case TPIC_CODE('w', 'h'):
case TPIC_CODE('b', 'k'):
return 1;
default:
/* it's not a tpic special */
return 0;
}
}
switch (TPIC_CODE(arg[0], arg[1])) {
case TPIC_CODE('p', 'n'):
{
long n;
if (sscanf(arg + 2, "%ld", &n) != 1) {
message(ERROR, "bad argument to pn special");
return 1;
}
current_pen_size = n;
break;
}
case TPIC_CODE('p', 'a'):
{
long x, y;
if (sscanf(arg + 2, "%ld %ld", &x, &y) != 2) {
message(ERROR, "bad arguments to pa special");
return 1;
}
if (npoints >= maxpoints) {
if (maxpoints == 0) {
point_vector = (struct point *)
malloc((maxpoints = 5)*sizeof(struct point));
if (point_vector == NULL)
out_of_memory();
}
else {
point_vector = (struct point *)
realloc((char *)point_vector,
sizeof(struct point)*(maxpoints *= 2));
if (point_vector == NULL)
out_of_memory();
}
}
point_vector[npoints].x = x;
point_vector[npoints].y = y;
npoints++;
break;
}
case TPIC_CODE('s', 'p'):
{
float f;
if (sscanf(arg + 2, "%f", &f) == 1 && f != 0.0) {
if (f > 0.0) {
tpic_flags |= DASHED;
dash_width = f;
}
else {
tpic_flags |= DOTTED;
dash_width = -f;
}
}
tpic_flags |= SPLINE;
goto path;
}
case TPIC_CODE('d', 'a'):
{
float f;
if (sscanf(arg + 2, "%f", &f) != 1) {
message(ERROR, "bad argument to da special");
return 1;
}
tpic_flags |= DASHED;
dash_width = f;
goto path;
}
case TPIC_CODE('d', 't'):
{
float f;
if (sscanf(arg + 2, "%f", &f) != 1) {
message(ERROR, "bad argument to dt special");
return 1;
}
tpic_flags |= DOTTED;
dash_width = f;
goto path;
}
case TPIC_CODE('i', 'p'):
tpic_flags |= INVISIBLE;
/* fall through */
case TPIC_CODE('f', 'p'):
path:
{
struct tpic_object *p;
size_t sz = sizeof(struct tpic_object);
if (npoints > 2)
sz += sizeof(struct point)*(npoints - 2);
p = (struct tpic_object *)malloc(sz);
if (p == NULL)
out_of_memory();
p->flags = tpic_flags;
if (tpic_flags & (DOTTED|DASHED))
p->u.p.dash_width = dash_width;
tpic_flags = 0;
memcpy((char *)p->u.p.point_vector, (char *)point_vector,
npoints*sizeof(struct point));
p->u.p.npoints = npoints;
npoints = 0;
p->next = tpic_object_list;
tpic_object_list = p;
complete = 1;
break;
}
case TPIC_CODE('i', 'a'):
tpic_flags |= INVISIBLE;
/* fall through */
case TPIC_CODE('a', 'r'):
{
struct tpic_object *p;
long x, y;
long rx, ry;
float s, e;
if (sscanf(arg + 2, "%ld %ld %ld %ld %f %f",
&x, &y, &rx, &ry, &s, &e) != 6) {
if (arg[0] == 'i')
message(ERROR, "bad argument to ia special");
else
message(ERROR, "bad argument to ar special");
return 1;
}
p = (struct tpic_object *)malloc(sizeof(struct tpic_object));
if (p == NULL)
out_of_memory();
p->flags = ARC|tpic_flags;
tpic_flags = 0;
p->u.a.cx = x;
p->u.a.cy = y;
p->u.a.rx = rx;
p->u.a.ry = ry;
p->u.a.s = s;
p->u.a.e = e;
p->next = tpic_object_list;
tpic_object_list = p;
complete = 1;
break;
}
case TPIC_CODE('s', 'h'):
{
float f;
if (sscanf(arg + 2, "%f", &f) != 1)
f = 0.5;
tpic_flags |= SHADED;
shade = f;
break;
}
case TPIC_CODE('w', 'h'):
tpic_flags |= SHADED;
shade = 0.0;
break;
case TPIC_CODE('b', 'k'):
tpic_flags |= SHADED;
shade = 1.0;
break;
default:
/* it's not a tpic special */
return 0;
}
if (complete) {
/* we just completed an object, so fill in some details */
tpic_object_list->h = x;
tpic_object_list->v = y;
tpic_object_list->region = current_region;
tpic_object_list->pen_size = current_pen_size;
if (tpic_object_list->flags & DOTTED)
tpic_object_list->pen_size += DOTTED_LINE_WIDTH_ADDITION;
if (tpic_object_list->flags & SHADED)
tpic_object_list->shade = shade;
}
return 1;
}
#define round(d) ((long)((d) + 0.5))
void p_tpic_list(psfp, page)
FILE *psfp;
struct page_info *page;
{
int r = NO_REGION;
integer ox = 0, oy = 0;
integer ps = -1;
double sc = (254.0*page->den)/page->num;
struct tpic_object *p = tpic_object_list;
if (p == NULL)
return;
/* reverse tpic_object_list */
tpic_object_list = NULL;
while (p != NULL) {
struct tpic_object *tem = p;
p = p->next;
tem->next = tpic_object_list;
tpic_object_list = tem;
}
fputs("BO TP\n", psfp);
while (tpic_object_list != NULL) {
p = tpic_object_list;
if (p->region != r) {
if (r != NO_REGION)
fputs("GR\n", psfp);
if (p->region != NO_REGION) {
fputs("GS\n", psfp);
do_transform(p->region, &ox, &oy, psfp);
}
else
ox = oy = 0;
r = p->region;
}
p->h -= ox;
p->v -= oy;
if (p->pen_size != ps) {
ps = p->pen_size;
put_dim(round(ps*sc), psfp);
fputs(" LW\n", psfp);
}
if (p->flags & ARC) {
integer cx, cy, rx, ry;
double s, e;
cx = p->u.a.cx;
cy = p->u.a.cy;
rx = p->u.a.rx;
ry = p->u.a.ry;
s = p->u.a.s;
e = p->u.a.e;
if (e - s >= M_PI*2.0) {
if (p->flags & SHADED) {
if (p->shade != 1.0)
fprintf(psfp, "%g SG\n", 1 - p->shade);
draw_ellipse(psfp, sc, p->h, p->v, cx, cy, rx, ry);
fputs("FI\n", psfp);
if (p->shade != 1.0)
fputs("0 SG\n", psfp);
}
if (!(p->flags & INVISIBLE)) {
draw_ellipse(psfp, sc, p->h, p->v, cx, cy, rx, ry);
fputs("ST\n", psfp);
}
}
else {
if (rx != ry)
message(WARNING, "open arc with rx != ry");
draw_arc(psfp, sc, p->h, p->v, cx, cy, rx, s, e);
fputs("ST\n", psfp);
}
}
else {
int np = p->u.p.npoints;
struct point *pv = p->u.p.point_vector;
double dw = p->u.p.dash_width*1000.0;
if (p->flags & SPLINE) {
if (p->flags & DASHED) {
put_dim(round(sc*dw), psfp);
putc(' ', psfp);
put_dim(round(sc*dw), psfp);
fputs(" DH\n", psfp);
}
else if (p->flags & DOTTED) {
fputs("0 ", psfp);
put_dim(round(sc*dw), psfp);
fputs(" DH\n", psfp);
}
draw_spline(psfp, sc, p->h, p->v, pv, np);
fputs("ST\n", psfp);
if (p->flags & (DOTTED|DASHED))
fputs("SO\n", psfp);
}
else {
int closed = (np >= 2
&& pv[0].x == pv[np - 1].x
&& pv[0].y == pv[np - 1].y);
if (p->flags & SHADED) {
if (p->shade != 1.0)
fprintf(psfp, "%g SG\n", 1 - p->shade);
draw_path(psfp, sc, p->h, p->v, pv, np - (closed != 0), 1);
fputs("FI\n", psfp);
if (p->shade != 1.0)
fputs("0 SG\n", psfp);
}
if (!(p->flags & INVISIBLE)) {
if (p->flags & DOTTED) {
int i;
for (i = 0; i < np - 1; i++) {
double x = pv[i+1].x - pv[i].x;
double y = pv[i+1].y - pv[i].y;
double dist = sqrt(x*x + y*y);
double adw;
if (dist <= dw)
adw = dist;
else
adw = dist/round(dist/dw);
fputs("0 ", psfp);
put_dim(round(sc*adw), psfp);
fputs(" DH\n", psfp);
draw_path(psfp, sc, p->h, p->v, pv + i, 2, 0);
fputs("ST\n", psfp);
}
fputs("SO\n", psfp);
}
else if (p->flags & DASHED) {
int i;
for (i = 0; i < np - 1; i++) {
double x = pv[i+1].x - pv[i].x;
double y = pv[i+1].y - pv[i].y;
double dist = sqrt(x*x + y*y);
double adw, gw;
if (dist <= dw*2.0) {
adw = dist;
gw = 0.0;
}
else {
int ndashes = (int)(ceil((dist - dw)/(dw*2.0)));
gw = (dist - dw)/ndashes - dw;
adw = dw;
}
put_dim(round(sc*adw), psfp);
putc(' ', psfp);
put_dim(round(sc*gw), psfp);
fputs(" DH\n", psfp);
draw_path(psfp, sc, p->h, p->v, pv + i, 2, 0);
fputs("ST\n", psfp);
}
fputs("SO\n", psfp);
}
else {
draw_path(psfp, sc, p->h, p->v, pv,
np - (closed != 0), closed);
fputs("ST\n", psfp);
}
}
}
}
tpic_object_list = tpic_object_list->next;
free((char *)p);
}
if (r != NO_REGION)
fputs("GR\n", psfp);
fputs("EO\n", psfp);
}
static void draw_path(psfp, sc, ox, oy, pv, np, closed)
FILE *psfp;
double sc;
integer ox, oy;
struct point *pv;
int np;
int closed;
{
int i;
put_dim(ox + round(pv[0].x*sc), psfp);
putc(' ', psfp);
put_dim(oy + round(pv[0].y*sc), psfp);
fputs(" MT\n", psfp);
for (i = 1; i < np; i++) {
put_dim(ox + round(pv[i].x*sc), psfp);
putc(' ', psfp);
put_dim(oy + round(pv[i].y*sc), psfp);
fputs(" LT\n", psfp);
}
if (closed)
fputs("CP\n", psfp);
}
static void draw_spline(psfp, sc, ox, oy, pv, np)
FILE *psfp;
double sc;
integer ox, oy;
struct point *pv;
int np;
{
int i;
put_dim(ox + round(pv[0].x*sc), psfp);
putc(' ', psfp);
put_dim(oy + round(pv[0].y*sc), psfp);
fputs(" MT\n", psfp);
put_dim(ox + round((pv[0].x+pv[1].x)*sc/2.0), psfp);
putc(' ', psfp);
put_dim(oy + round((pv[0].y+pv[1].y)*sc/2.0), psfp);
fputs(" LT\n", psfp);
for (i = 1; i < np - 1; i++) {
put_dim(ox + round((pv[i-1].x + 5*pv[i].x)*sc/6.0), psfp);
putc(' ', psfp);
put_dim(oy + round((pv[i-1].y + 5*pv[i].y)*sc/6.0), psfp);
putc(' ', psfp);
put_dim(ox + round((5*pv[i].x + pv[i+1].x)*sc/6.0), psfp);
putc(' ', psfp);
put_dim(oy + round((5*pv[i].y + pv[i+1].y)*sc/6.0), psfp);
putc(' ', psfp);
put_dim(ox + round((pv[i].x+pv[i+1].x)*sc/2.0), psfp);
putc(' ', psfp);
put_dim(oy + round((pv[i].y+pv[i+1].y)*sc/2.0), psfp);
fputs(" CT\n", psfp);
}
put_dim(ox + round(pv[np - 1].x*sc), psfp);
putc(' ', psfp);
put_dim(oy + round(pv[np - 1].y*sc), psfp);
fputs(" LT\n", psfp);
}
static void draw_ellipse(psfp, sc, ox, oy, cx, cy, rx, ry)
FILE *psfp;
double sc;
integer ox, oy;
integer cx, cy, rx, ry;
{
put_dim(round(rx*sc), psfp);
putc(' ', psfp);
put_dim(round(ry*sc), psfp);
putc(' ', psfp);
put_dim(ox + round(sc*cx), psfp);
putc(' ', psfp);
put_dim(oy + round(sc*cy), psfp);
fputs(" EL\n", psfp);
}
static void draw_arc(psfp, sc, ox, oy, cx, cy, r, s, e)
FILE *psfp;
double sc;
integer ox, oy;
integer cx, cy, r;
double s, e;
{
put_dim(ox + round(sc*cx), psfp);
putc(' ', psfp);
put_dim(oy + round(sc*cy), psfp);
putc(' ', psfp);
put_dim(round(sc*r), psfp);
fprintf(psfp, " %g %g AR\n", s*180.0/M_PI, e*180.0/M_PI);
}
#endif
/*
Local Variables:
c-indent-level: 4
c-continued-statement-offset: 4
c-brace-offset: -4
c-argdecl-indent: 0
c-label-offset: -4
tab-width: 4
End:
*/